/*
PearReview - The peer review assistant.
Copyright (C) 2009  Dimitrij Pankratz, Anton Musichin
http://www.pearreview.com, info@pearreview.com

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

package com.pearreview.scribeplugin;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Formatter;

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import com.pearreview.application.Messages;
import com.pearreview.util.pdf.PChunk;
import com.pearreview.util.pdf.PParagraph;
import com.pearreview.util.pdf.PdfFindingsWriter;
import com.pearreview.util.pdf.PdfImage;
import com.pearreview.util.pdf.PdfImageWriter;
import com.pearreview.util.pdf.PdfPageEventOld;
import com.pearreview.util.review.AttendeeRole;
import com.pearreview.util.review.Finding;
import com.pearreview.util.review.Meeting;
import com.pearreview.util.review.Review;

public class PDFProtocolWriter extends AbstractProtocolWriter
		implements ProtocolWriter {

	private static final long serialVersionUID = -1172066419461627886L;

	public static final String PDF_EXTENSION = ".pdf";
	
	private boolean attachFiles;
	private boolean createSignatureFields = true;
	private boolean reviewProtocol = false;
	private boolean printImages = false;
	private int imageNumber = 0;
	private ArrayList<PdfImage> fImages = new ArrayList<PdfImage>();

	public PDFProtocolWriter() {
		this(false);
	}
	
	public PDFProtocolWriter(boolean attachFiles) {
		this.setAttachFiles(attachFiles);
	}
	
	@Override
	public void setPrintImages(boolean printImages) {
		this.printImages = printImages;
	}
	
	@Override
	public boolean isCreateSignatureFields() {
		return createSignatureFields;
	}

	@Override
	public void setCreateSignatureFields(boolean createSignatureFields) {
		this.createSignatureFields = createSignatureFields;
	}

	@Override
	public boolean isReviewProtocol() {
		return reviewProtocol;
	}

	@Override
	public void setReviewProtocol(boolean reviewProtocol) {
		this.reviewProtocol = reviewProtocol;
	}
	
	@Override
	public void write(Review review, Meeting meeting,
			OutputStream outputStream) throws DocumentException, IOException {
		
		fImages = new ArrayList<PdfImage>();
		
		//padding left, right, top, bottom = 50, 50, 50, 50
		Document doc = new Document(PageSize.A4, 50, 50, 50, 50);
		
		PdfWriter writer = PdfWriter.getInstance(doc, outputStream);
		//writer.setViewerPreferences(PdfWriter.FitWindow);
		PdfDestination dest = new PdfDestination(PdfDestination.FIT);
		writer.setViewerPreferences(PdfWriter.CenterWindow); 
		
		String reviewName = (isEmpty(review.getName()))?
				getEmptyField():
				review.getName();
				
		writer.setPageEvent(new PdfPageEventOld(Messages.getString(
				"PearReview.protocol.protocol") + " - " + reviewName));

		doc.open();
		
		new PdfOutline(writer.getDirectContent().getRootOutline(), dest, 
				Messages.getString("PearReview.protocol.protocol"));
			

		//add heading
		createMainText(doc, "Review " + 
				Messages.getString("PearReview.protocol.protocol"));
		
		PdfContentByte cb = writer.getDirectContent();
		cb.setColorStroke(new GrayColor(0.2f));
		cb.setColorFill(new GrayColor(0.9f));
		cb.moveTo(50, 730);
		cb.lineTo(545, 730);
		cb.closePathFillStroke();
		
		//write meeting date
		if (meeting.getProtocol() != null && !reviewProtocol)
			writeMeetingDate(meeting, doc);
		
		//add all available attendees
		if (meeting.getProtocol() != null && !reviewProtocol)
			writeAttendees(meeting, doc, createSignatureFields);
		
		//add results
		createResultText(review, doc);
		
		//write canceled reason
		boolean canceled = false;
		if (meeting.getCanceled() != null)
			canceled = true;
		if (!reviewProtocol)
			writeCanceled(meeting, doc, canceled);
		
		
		if (!reviewProtocol)
			doc.newPage();
		
		//add review info
		writeReviewInformation(review, doc);
		
		//add product info
		createProductText(review, doc);
		
		//add meeting info
		if (reviewProtocol) {
			for (Meeting cMeeting: review.getMeetings()) {
				if (cMeeting != null) {
					if (cMeeting.getProtocol() != null)
						this.writeMeetingInformation(cMeeting, doc);
				}
			}
		} else {
			if (meeting.getProtocol() != null)
				this.writeMeetingInformation(meeting, doc);
		}
		
		
		//add findings
		if (reviewProtocol) {
			for (Meeting cMeeting: review.getMeetings()) {
				if (cMeeting.getProtocol() != null)
					if (cMeeting.getProtocol().getFindings() != null &&
							cMeeting.getProtocol().getFindings().size() > 0) {
						doc.newPage();
						PdfFindingsWriter findinsWriter = 
							new PdfFindingsWriter(doc, writer);
						findinsWriter.writeFindings(
								cMeeting.getProtocol().getFindings(), fImages, 
								printImages, imageNumber);
					}
			}
		} else {
			doc.newPage();
			if (meeting.getProtocol().getFindings() != null &&
					meeting.getProtocol().getFindings().size() > 0) {
				PdfFindingsWriter findinsWriter = 
					new PdfFindingsWriter(doc, writer);
				findinsWriter.writeFindings(
						meeting.getProtocol().getFindings(), fImages, 
						printImages, imageNumber);
			}
		}
		
		
		//add images
		if (printImages) {
			if (reviewProtocol) {
				for (Meeting cMeeting: review.getMeetings()) {
					if (cMeeting.getProtocol() != null)
						if (cMeeting.getProtocol().getFindings() != null &&
								cMeeting.getProtocol()
								.getFindings().size() > 0) {
							doc.newPage();
							new PdfImageWriter().writeImages(fImages, doc, writer);
						}
				}
			} else {
				doc.newPage();
				if (meeting.getProtocol().getFindings() != null &&
						meeting.getProtocol().getFindings().size() > 0) {
					new PdfImageWriter().writeImages(fImages, doc, writer);
				}
			}
		}
		
		if (fImages.size() > 0)
			writer.setViewerPreferences(PdfWriter.PageModeUseAttachments);
		
		doc.close();
		
		writer.close();
	}

	
	@Override
	public String getFileExtension() {
		return PDF_EXTENSION;
	}
	
	protected void attachFiles(PdfWriter writer, Finding finding) 
			throws IOException {
		/* API doc
		 * 
		public void PdfWriter::addFileAttachment(String description,
                byte[] fileStore,
                String file,
                String fileDisplay)
         throws IOException
         */
		
		for(URI ref: finding.getExternalReferences()) {
			File file = new File(ref);
			String description =Messages.getString(
					"PearReview.protocol.external_reference.description");
			
			Formatter formatter = new Formatter();
			description = 
					formatter.format(description, finding.getId()).toString();
			
			writer.addFileAttachment(description, 
					null, 
					file.toString(), 
					file.getName());
		}
	}
	
	/*
	private void writeLogo(Document doc, float height, String logoFile) 
			throws IOException, DocumentException {
		Image img = Image.getInstance(logoFile);
		img.scaleToFit(200, 200);
		img.setAlignment(Image.RIGHT | Image.TEXTWRAP);
		doc.add(img);
	}
	*/
	
	private void createMainText(Document doc, String text) 
			throws DocumentException {
		
		PChunk cHeading = new PChunk(text);
		Font font = cHeading.getFont();
		font.setStyle(Font.BOLD);
		font.setSize(20f);
		cHeading.setFont(font);

		PParagraph pHeading = new PParagraph();
		pHeading.setAlignment(Element.ALIGN_CENTER);
		pHeading.add(cHeading);
		pHeading.setSpacingAfter(30f);
		
		PParagraph pSpace = new PParagraph(" ");
		//pSpace.setSpacingAfter(20f);
		
		doc.add(pSpace);
		doc.add(pHeading);
		
	}
	
	/**
	 * 
	 * @param review
	 * @param doc
	 * @throws DocumentException
	 */
	private void createResultText(Review review, Document doc) 
			throws DocumentException {
		
		PParagraph pFirst = new PParagraph();
		pFirst.setSpacingAfter(40f);
		doc.add(pFirst);
		
		PChunk cHeading = new PChunk(Messages.getString(
				"PearReview.protocol.result"));
		
		Font font = cHeading.getFont();
		font.setColor(new BaseColor(0x333333));
		font.setSize(16);
		font.setStyle(Font.BOLD);
		
		PParagraph pHeading = new PParagraph();
		pHeading.setSpacingAfter(20);
		pHeading.add(cHeading);
		
		doc.add(pHeading);

		PdfPTable table = new PdfPTable(2);
		float[] widths = { 1f, 1f};
		table.setWidths(widths);
		table.setWidthPercentage(100);
		
		
		PParagraph pName = new PParagraph();
		PChunk caption = new PChunk(Messages.getString(
				"PearReview.protocol.general_impression"));
		font = caption.getFont();
		font.setStyle(Font.BOLD);
		font.setSize(12);
		font.setColor(new BaseColor(0x000000));
		pName.add(caption);
		PdfPCell cell = new PdfPCell(pName);
		cell.setBorder(Rectangle.NO_BORDER);
		cell.setPaddingRight(10);
		cell.setPaddingBottom(10);
		table.addCell(cell);
		
		
		pName = new PParagraph();
		caption = new PChunk(Messages.getString(
				"PearReview.protocol.final_recommendation"));
		font = caption.getFont();
		font.setStyle(Font.BOLD);
		font.setSize(12);
		font.setColor(new BaseColor(0x000000));
		pName.add(caption);
		cell = new PdfPCell(pName);
		cell.setBorder(Rectangle.NO_BORDER);
		cell.setPaddingBottom(10);
		table.addCell(cell);
		
		
		pName = new PParagraph();
		PChunk content = (isEmpty(review.getImpression()))?
				this.getEmptyFieldPChunk():
				new PChunk(review.getImpression());
		pName.add(content);
		cell = new PdfPCell(pName);
		cell.setBorder(Rectangle.NO_BORDER);
		cell.setPaddingRight(10);
		table.addCell(cell);
		
		
		pName = new PParagraph();
		content = (isEmpty(review.getRecommendation()))?
				this.getEmptyFieldPChunk():
				new PChunk(review.getRecommendation());
		pName.add(content);
		cell = new PdfPCell(pName);
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		doc.add(table);
		
		PParagraph pLast = new PParagraph();
		pLast.setSpacingAfter(40f);

		doc.add(pLast);
	}
	
	/**
	 * 
	 * @param review
	 * @param doc
	 * @throws DocumentException
	 */
	private void createProductText(Review review, Document doc) 
			throws DocumentException {
		PChunk cHeading = new PChunk(Messages.getString(
				"PearReview.invitation.product_information"));
		Font font = cHeading.getFont();
		font.setStyle(Font.BOLD);
		font.setColor(new BaseColor(0x333333));
		font.setSize(16);
		
		PParagraph pHeading = new PParagraph();
		pHeading.setSpacingAfter(20);
		pHeading.add(cHeading);
		
		doc.add(pHeading);
		
		PdfPTable table = new PdfPTable(2);
		float[] widths = { 1f, 3f};
		table.setWidths(widths);
		table.setWidthPercentage(100);
		
		//add product name
		PChunk caption = new PChunk(Messages.getString(
				"PearReview.Moderator.review.name_2") + ": ");
		font = caption.getFont();
		font.setColor(new BaseColor(0x000000));
		font.setStyle(Font.BOLD);
		
		PChunk content = (isEmpty(review.getProduct().getName()))?
				getEmptyFieldPChunk():
				new PChunk(review.getProduct().getName());
		
		PdfPCell cell = new PdfPCell(new PParagraph(caption));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
				
		cell = new PdfPCell(new PParagraph(content));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		//add product version
		caption = new PChunk(Messages.getString(
				"PearReview.invitation.version") + ": ");
		font = caption.getFont();
		font.setColor(new BaseColor(0x000000));
		font.setStyle(Font.BOLD);
		
		content = (isEmpty(review.getProduct().getVersion()))?
				getEmptyFieldPChunk():
				new PChunk(review.getProduct().getVersion());
		
		cell = new PdfPCell(new PParagraph(caption));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
				
		cell = new PdfPCell(new PParagraph(content));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		
		//add product references
		ArrayList<File> fileRef = new ArrayList<File>();
		ArrayList<String> stringRef = new ArrayList<String>();
		
		if(review.getProduct().getReference() != null) {
			for(String ref: review.getProduct().getReference()) {
				File file = getFile(ref);
				if (file != null) {
					fileRef.add(file);
				} else {
					stringRef.add(ref);
				}
			}
		}
		
		
		caption = new PChunk(Messages.getString(
				"PearReview.invitation.references") + ": ");
		font = caption.getFont();
		font.setStyle(Font.BOLD);
		font.setColor(new BaseColor(0x000000));
		cell = new PdfPCell(new PParagraph(caption));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		cell = new PdfPCell(new PParagraph());
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		
		PParagraph cList = new PParagraph();
		
		for (String ref: stringRef) {
			cList.add(ref);
			cList.add("\n");
		}
		
		PParagraph pCap = new PParagraph(Messages.getString(
				"PearReview.invitation.text_references"));
		cell = new PdfPCell(pCap);
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		PParagraph p = new PParagraph();
		
		if (stringRef.size() > 0) {
			p.add(cList);
		} else {
			p.add(getEmptyFieldPChunk());
		}

		cell = new PdfPCell(p);
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		
		cList = new PParagraph();
		
		for (File ref: fileRef) {
			cList.add(ref.getName());
			cList.add("\n");
		}
		
		pCap = new PParagraph(Messages.getString(
			"PearReview.invitation.file_references"));
		cell = new PdfPCell(pCap);
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		p = new PParagraph();
		
		if (fileRef.size() > 0) {
			p.add(cList);
		} else {
			p.add(getEmptyFieldPChunk());
		}
		
		cell = new PdfPCell(p);
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
	
		doc.add(table);
		
		PParagraph pLast = new PParagraph();
		pLast.setSpacingAfter(40f);

		doc.add(pLast);
	}
	
	
	/**
	 * Create and add review information.
	 * 
	 * @param review
	 * @param doc
	 * @throws DocumentException
	 */
	private void writeReviewInformation(Review review, Document doc) 
			throws DocumentException {
		PChunk cHeading = new PChunk(Messages.getString(
		"PearReview.invitation.review_information"));
		Font font = cHeading.getFont();
		font.setColor(new BaseColor(0x333333));
		font.setStyle(Font.BOLD);
		font.setSize(16);
		
		PParagraph pHeading = new PParagraph();
		pHeading.setSpacingAfter(20);
		pHeading.add(cHeading);
		
		doc.add(pHeading);
		
		PdfPTable table = new PdfPTable(2);
		float[] widths = { 1f, 3f};
		table.setWidths(widths);
		table.setWidthPercentage(100);
		
		//add review name
		PChunk caption = new PChunk(Messages.getString(
				"PearReview.Moderator.review.name_2") + ": ");
		font = caption.getFont();
		font.setColor(new BaseColor(0x000000));
		font.setStyle(Font.BOLD);
		
		PChunk content = (isEmpty(review.getName()))?
				getEmptyFieldPChunk():
				new PChunk(review.getName());
		
		PdfPCell cell = new PdfPCell(new PParagraph(caption));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		cell = new PdfPCell(new PParagraph(content));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		//add review description
		caption = new PChunk(Messages.getString(
				"PearReview.Moderator.review.description") + ": ");
		font = caption.getFont();
		font.setColor(new BaseColor(0x000000));
		font.setStyle(Font.BOLD);
		
		content = (isEmpty(review.getDescription()))?
				getEmptyFieldPChunk():
				new PChunk(review.getDescription());
		
		cell = new PdfPCell(new PParagraph(caption));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		cell = new PdfPCell(new PParagraph(content));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		//add review comments
		caption = new PChunk(Messages.getString(
				"PearReview.Moderator.review.comments") + ": ");
		font = caption.getFont();
		font.setColor(new BaseColor(0x000000));
		font.setStyle(Font.BOLD);
		
		content = (isEmpty(review.getComments()))?
				getEmptyFieldPChunk():
				new PChunk(review.getComments());
		
		cell = new PdfPCell(new PParagraph(caption));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
				
		cell = new PdfPCell(new PParagraph(content));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		doc.add(table);
		
		PParagraph pLast = new PParagraph();
		pLast.setSpacingAfter(40f);

		doc.add(pLast);
	}
	
	
	/**
	 * Create and add meeting information.
	 * 
	 * @param meeting
	 * @param doc
	 * @throws DocumentException
	 */
	private void writeMeetingInformation(Meeting meeting, Document doc) 
			throws DocumentException {
		
		PChunk cHeading = new PChunk(Messages.getString(
				"PearReview.invitation.review_meeting"));
		Font font = cHeading.getFont();
		font.setColor(new BaseColor(0x333333));
		font.setStyle(Font.BOLD);
		font.setSize(16);
		
		PParagraph pHeading = new PParagraph();
		pHeading.setSpacingAfter(10);
		pHeading.add(cHeading);
		
		doc.add(pHeading);
		
		PdfPTable table = new PdfPTable(2);
		float[] widths = { 1f, 3f};
		table.setWidths(widths);
		table.setWidthPercentage(100);
		
		//add meeting location
		PChunk caption = new PChunk(Messages.getString(
				"PearReview.Moderator.meetings.place") + ": ");
		font = caption.getFont();
		font.setColor(new BaseColor(0x000000));
		font.setStyle(Font.BOLD);
		PdfPCell cell = new PdfPCell(new PParagraph(caption));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		PChunk content = (isEmpty(meeting.getProtocol().getLocation()))?
				getEmptyFieldPChunk():
				new PChunk(meeting.getProtocol().getLocation());
		cell = new PdfPCell(new PParagraph(content));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		
		//add meeting date
		caption = new PChunk(Messages.getString(
				"PearReview.Moderator.meetings.date") + ": ");
		font = caption.getFont();
		font.setColor(new BaseColor(0x000000));
		font.setStyle(Font.BOLD);
		
		content = (meeting.getProtocol().getDate()==null)?
				getEmptyFieldPChunk():
				new PChunk(DateFormat.getDateInstance().format(
				meeting.getProtocol().getDate().getTime()));
		
		cell = new PdfPCell(new PParagraph(caption));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		cell = new PdfPCell(new PParagraph(content));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		
		//add meeting start
		caption = new PChunk(Messages.getString(
				"PearReview.Moderator.meetings.start") + ": ");
		font = caption.getFont();
		font.setColor(new BaseColor(0x000000));
		font.setStyle(Font.BOLD);
		
		content = (meeting.getProtocol().getStart() == null)?
				getEmptyFieldPChunk():
				new PChunk(DateFormat.getTimeInstance(
				DateFormat.SHORT).format(
						meeting.getProtocol().getStart().getTime()));
		
		cell = new PdfPCell(new PParagraph(caption));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		cell = new PdfPCell(new PParagraph(content));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		
		//add meeting end
		caption = new PChunk(Messages.getString(
				"PearReview.Moderator.meetings.end") + ": ");
		font = caption.getFont();
		font.setColor(new BaseColor(0x000000));
		font.setStyle(Font.BOLD);
		
		content = (meeting.getProtocol().getEnd() == null)?
				getEmptyFieldPChunk():
				new PChunk(DateFormat.getTimeInstance(
				DateFormat.SHORT)
				.format(meeting.getProtocol().getEnd().getTime()));
		
		cell = new PdfPCell(new PParagraph(caption));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		cell = new PdfPCell(new PParagraph(content));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		
		//add meeting comments
		caption = new PChunk(Messages.getString(
				"PearReview.Moderator.meetings.comments") + ": ");
		font = caption.getFont();
		font.setColor(new BaseColor(0x000000));
		font.setStyle(Font.BOLD);
		
		content = (isEmpty(meeting.getProtocol().getComments()))?
				getEmptyFieldPChunk():
				new PChunk(meeting.getProtocol().getComments());
		
		cell = new PdfPCell(new PParagraph(caption));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		cell = new PdfPCell(new PParagraph(content));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		
		doc.add(table);
		
		PParagraph pLast = new PParagraph();
		pLast.setSpacingAfter(40f);

		doc.add(pLast);
	}
	
	/**
	 * Create and add meeting information.
	 * 
	 * @param meeting
	 * @param doc
	 * @throws DocumentException
	 */
	private void writeMeetingDate(Meeting meeting, Document doc) 
			throws DocumentException {
		
		//add meeting date
		PChunk caption = new PChunk(Messages.getString(
				"PearReview.protocol.meeting_from") + " ");
		
		PChunk content = (meeting.getProtocol().getDate()==null)?
				getEmptyFieldPChunk():
				new PChunk(DateFormat.getDateInstance().format(
				meeting.getProtocol().getDate().getTime()));
		
		PParagraph p = new PParagraph();
		Font font = p.getFont();
		font.setStyle(Font.ITALIC);
		p.add(caption);
		p.add(content);
		p.setAlignment(Element.ALIGN_RIGHT);

		doc.add(p);
		
		PParagraph pLast = new PParagraph();
		pLast.setSpacingAfter(30f);

		doc.add(pLast);
	}
	
	/**
	 * Create sign fields for available attendees.
	 * 
	 * @param meeting
	 * @param doc
	 * @throws DocumentException
	 */
	private void writeAttendees(Meeting meeting, Document doc, 
			boolean signatures) throws DocumentException {
		if (meeting.getProtocol() != null) {
			
			PdfPTable table;
			if (signatures) {
				table = new PdfPTable(2);
				float[] widths = { 1f, 1f};
				table.setWidths(widths);
				table.setWidthPercentage(100);
				table.setHeaderRows(1);
			} else {
				table = new PdfPTable(1);
				float[] widths = { 1f };
				table.setWidths(widths);
				table.setWidthPercentage(100);
				table.setHeaderRows(1);
			}
			
			PChunk c1 = new PChunk(Messages.getString(
					"PearReview.Moderator.tabs.attendees"));
			PParagraph p1 = new PParagraph();
			Font font = c1.getFont();
			font.setColor(new BaseColor(0x333333));
			font.setStyle(Font.BOLD);
			font.setSize(16);
			p1.add(c1);
			PdfPCell h1 = new PdfPCell(p1);
			h1.setBorder(Rectangle.NO_BORDER);
			h1.setPaddingBottom(20f);
			
			PChunk c2 = new PChunk(Messages.getString(
					"PearReview.protocol.signatures"));
			PParagraph p2 = new PParagraph();
			font = c2.getFont();
			font.setStyle(Font.BOLD);
			font.setColor(new BaseColor(0x333333));
			font.setSize(16);
			p2.add(c2);
			PdfPCell h2 = new PdfPCell(p2);
			h2.setBorder(Rectangle.NO_BORDER);
			h2.setPaddingBottom(20f);
			
			table.addCell(h1);
			
			if (signatures)
				table.addCell(h2);
			
			
			for (int i=0; i<meeting.getProtocol().getAvailableAttendees()
					.size(); i++) {
				String name = meeting.getProtocol().getAvailableAttendees()
						.get(i).getName(); 
				String role = getRoleString(meeting.getProtocol()
							.getAvailableAttendees().get(i).getRole());
				
				PChunk c = null;
				if (isEmpty(name)) {
					c = this.getEmptyFieldPChunk();
				} else {
					c = new PChunk(name);
				}
				font = c.getFont();
				font.setColor(new BaseColor(0x000000));
				font.setStyle(Font.BOLD);
				
				c2 = new PChunk(role);
				
				PParagraph p = new PParagraph();
				p.add(c);
				p.add(c2);
				p.add("\n");
				
				String text = "";
				if (meeting.getProtocol().getAvailableAttendees()
						.get(i).getPreparationTime() != null) {
					text = Messages.getString(
							"PearReview.protocol.preparationtime") + 
							": " + millisToString(
							meeting.getProtocol().getAvailableAttendees()
							.get(i).getPreparationTime());
				} else {
					text = Messages.getString(
							"PearReview.protocol.preparationtime") + 
							": " + getEmptyField();
				}
				
				c = new PChunk(text);
				font = c.getFont();
				font.setColor(new BaseColor(0x000000));
				font.setStyle(Font.ITALIC);
				p.add(c);
				p.add("\n");
				
				p.setSpacingAfter(10f);
				PdfPCell cell = new PdfPCell(p);
				cell.setMinimumHeight(35f);
				cell.setBorder(Rectangle.NO_BORDER);
				table.addCell(cell);
				
				if (signatures)  {
					p = new PParagraph("\n");
					p.add("____________________________________");
					p.add("\n");
					cell = new PdfPCell(p);
					cell.setBorder(Rectangle.NO_BORDER);
					cell.setMinimumHeight(35f);
					table.addCell(cell);
				}
			}
			doc.add(table);
		}
	}
	
	
	/**
	 * 
	 * @param meeting
	 * @param doc
	 * @throws DocumentException
	 */
	private void writeCanceled(Meeting meeting, Document doc, boolean canceled) 
			throws DocumentException {
		if (meeting != null) {
			
			PChunk cHeading = new PChunk(Messages.getString(
					"PearReview.protocol.state"));
			
			Font font = cHeading.getFont();
			font.setColor(new BaseColor(0x333333));
			font.setStyle(Font.BOLD);
			font.setSize(16);
			
			PParagraph pHeading = new PParagraph();
			pHeading.setSpacingAfter(20);
			pHeading.add(cHeading);
			doc.add(pHeading);
			
			PdfPTable table = new PdfPTable(2);
			float[] widths = { 1f, 1f};
			table.setWidths(widths);
			table.setWidthPercentage(100);
			
			if (canceled) {
				PParagraph p = new PParagraph(Messages.getString(
					"PearReview.protocol.meeting_was_canceled"));
				font = p.getFont();
				font.setStyle(Font.BOLD);
				font.setColor(new BaseColor(0x000000));
				font.setSize(12);
				PdfPCell cell = new PdfPCell(p);
				cell.setBorder(Rectangle.NO_BORDER);
				table.addCell(cell);
				
				p = (isEmpty(meeting.getCanceled()))?
						new PParagraph(getEmptyFieldPChunk()):
						new PParagraph(meeting.getCanceled());
				cell = new PdfPCell(p);
				cell.setBorder(Rectangle.NO_BORDER);
				table.addCell(cell);

			} else {
				PParagraph p = new PParagraph("OK");
				font = p.getFont();
				font.setStyle(Font.BOLD);
				font.setColor(new BaseColor(0x000000));
				font.setSize(12);
				PdfPCell cell = new PdfPCell(p);
				cell.setBorder(Rectangle.NO_BORDER);
				table.addCell(cell);
				
				p = new PParagraph(Messages.getString(
						"PearReview.protocol.successed_meeting"));
				cell = new PdfPCell(p);
				cell.setBorder(Rectangle.NO_BORDER);
				table.addCell(cell);
			}
			
			doc.add(table);
				
			//PParagraph pLast = new PParagraph();
			//pLast.setSpacingAfter(40f);
			//doc.add(pLast);
		}
	}
	
	/**
	 * 
	 * @param aRole
	 * @return
	 */
	private String getRoleString(AttendeeRole aRole) {
		String role = "";
		
		switch (aRole) {
		case Moderator:
			role = Messages.getString("PearReview.review.modarator");
			break;
	
		case Scribe:
			role = Messages.getString("PearReview.review.scribe");
			break;
			
		case Reviewer:
			role = Messages.getString("PearReview.review.reviewer");
			break;
			
		case Author:
			role = Messages.getString("PearReview.review.author");
			break;
			
		case Customer:
			role = Messages.getString("PearReview.review.customer");
			break;
		}
		
		return " (" + role + ")";
	}

	public void setAttachFiles(boolean attachFiles) {
		this.attachFiles = attachFiles;
	}

	public boolean isAttachFiles() {
		return attachFiles;
	}
	
	public String millisToString(long millisTime) {
		
		millisTime /= 1000;
		int seconds = (int)(millisTime%60); millisTime /= 60;
		int minutes = (int)(millisTime%60); millisTime /= 60;
		int hours = (int)(millisTime%60);
		
		String secondsStr = Integer.toString(seconds); 
		if (seconds < 10)
			secondsStr = "0" + secondsStr;
		
		String minutesStr = Integer.toString(minutes); 
		if (minutes < 10)
			minutesStr = "0" + minutesStr;
		
		String hoursStr = Integer.toString(hours); 
		if (hours < 10)
			hoursStr = "0" + hoursStr;
			
		return hoursStr + ":" + minutesStr + " " + Messages.getString("" +
				"PearReview.protocol.hours");
	}
	
	private String getEmptyField() {
		return Messages.getString("PearReview.protocol.empty");
	}
	
	private PChunk getEmptyFieldPChunk() {
		PChunk c = new PChunk(getEmptyField());
		Font f = c.getFont();
		f.setStyle(Font.ITALIC);
		
		return c;
	}
	
	private boolean isEmpty(String str) {
		if (!(str == null || str.equals(""))) {
			return false;
		} else {
			return true;
		}
	}
}